AWS Glueをローカル環境で実行してみた
はじめに
CX事業本部の高橋雄大です。
2019年8月28日にGlue ETLライブラリのバイナリがリリースされました。このリリースにより、ローカルの開発環境でGlueのETLスクリプトを実行出来るようになりました。
AWS Glue、Glue ジョブ用 Glue ETL ライブラリのバイナリをリリース
目次
開発環境
項目 | バージョン | 備考 |
---|---|---|
macOS | Mojave 10.14.6 | |
AWS CLI | 1.16.233 | |
Apach Maven | 3.6.2 | Mavenをダウンロード |
Java Development Kit 8 (JDK) | 1.8 | JDKをダウンロード |
Apache Spark | 2.2.1 | Sparkをダウンロード |
Python | 2.7.1 | |
LocalStack | 0.10.2 | LocalStack |
環境変数を設定します。MavenとSparkのパスは個人の環境に合わせて変更してください。
echo 'export PATH=$HOME/.apache-maven-3.6.2/bin:$PATH' >> ~/.bash_profile echo 'export SPARK_HOME=$HOME/.spark-2.2.1-bin-hadoop2.7' >> ~/.bash_profile echo 'export JAVA_HOME=`/usr/libexec/java_home -v 1.8`' >> ~/.bash_profile
Pythonでローカル開発
AWS Glue Pythonライブラリを取得
GitHubからAWS Glue Pythonライブラリをダウンロードします。以降の作業はAWS Glue Pythonライブラリのルートディレクトリで行います。
https://github.com/awslabs/aws-glue-libs
PySparkをインストール
pipコマンドでpysparkパッケージをインストールします。
$ pip install pyspark
Apache Sparkの環境設定
Sparkの設定ファイルを作成します。DynamoDBとS3のエンドポイントをLocalStackに向けます。
spark.hadoop.dynamodb.endpoint http://localhost:4569 spark.hadoop.fs.s3a.endpoint http://localhost:4572 spark.hadoop.fs.s3a.path.style.access true spark.hadoop.fs.s3a.signing-algorithm S3SignerType
PythonでETLスクリプトを作成
DynamoDBから全ての項目を取得して、S3バケットに格納するスクリプトを作成してみます。
import sys from awsglue.transforms import ApplyMapping from awsglue.utils import getResolvedOptions from pyspark.context import SparkContext from awsglue.context import GlueContext from awsglue.job import Job from awsglue.dynamicframe import DynamicFrame DYNAMODB_INPUT_TABLE_NAME = 'aws-glue-local-test-table' S3_OUTPUT_BUCKET_NAME = 'aws-glue-local-test-bucket' args = getResolvedOptions(sys.argv, [ 'JOB_NAME' ]) JOB_NAME = args['JOB_NAME'] sc = SparkContext() glueContext = GlueContext(sc) job = Job(glueContext) job.init(JOB_NAME, args) datasource = glueContext.create_dynamic_frame.from_options( connection_type='dynamodb', connection_options={ 'dynamodb.input.tableName': DYNAMODB_INPUT_TABLE_NAME } ) applymapping = ApplyMapping.apply( frame=datasource, mappings=[ ('Id', 'string', 'Id', 'string'), ('Column1', 'string', 'Column1', 'string'), ('Column2', 'string', 'Column2', 'string'), ('Column3', 'string', 'Column3', 'string') ] ) glueContext.write_dynamic_frame.from_options( frame=datasource, connection_type='s3', connection_options={ 'path': 's3://' + S3_OUTPUT_BUCKET_NAME }, format='csv' ) job.commit()
ETLスクリプトの実行
LocalStackの準備
docker-compose
でLocalStackを立ち上げます。
version: "3.3" services: localstack: container_name: localstack image: localstack/localstack ports: - "8080:8080" - "4569:4569" - "4572:4572" environment: - DOCKER_HOST=unix:///var/run/docker.sock - DEFAULT_REGION=ap-northeast-1 - SERVICES=dynamodb,s3
$ docker-compose up -d
DynamoDBテーブルの準備
DynamoDBのテーブルを作成します。
$ aws dynamodb create-table \ --table-name aws-glue-local-test-table \ --attribute-definitions \ AttributeName=Id,AttributeType=S \ --key-schema AttributeName=Id,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \ --endpoint-url http://localhost:4569
テスト用のデータを登録します。
$ aws dynamodb put-item \ --table-name aws-glue-local-test-table \ --item \ '{"Id": {"S": "test"}, "Column1": {"S": "test1"}, "Column2": {"S": "test2"}, "Column3": {"S": "test3"}}' \ --endpoint-url http://localhost:4569
S3バケットの準備
S3のバケットを作成します。
$ aws s3api create-bucket \ --bucket aws-glue-local-test-bucket \ --endpoint-url http://localhost:4572
実行コマンド
AWS Glue Pythonパッケージのルートディレクトリで以下のコマンドを実行できます。
コマンド | 説明 |
---|---|
./bin/gluepyspark | ライブラリと統合するシェルにPythonスクリプトを入力して実行します。 |
./bin/gluesparksubmit | Pythonスクリプトを指定して実行します。 |
./bin/gluepytest | Pythonの単体テストを実行します。pytestモジュールが必要です。 |
動作確認
認証情報が設定されていないとエラーになるので、環境変数をセットしておきます。
$ export AWS_ACCESS_KEY_ID='dummy' $ export AWS_SECRET_ACCESS_KEY='dummy' $ export AWS_REGION='ap-northeast-1'
Pythonスクリプトを指定して実行します。--JOB_NAME
は必須なのでdummy
をセットしておきます。初回の実行時はGlue ETLライブラリのバイナリをダウンロードしてくるので、多少時間がかかります。
$ ./bin/gluesparksubmit ./src/sample.py --JOB_NAME='dummy'
S3バケットにCSVファイルが作成されていることを確認します。
$ aws s3api list-objects \ --bucket aws-glue-local-test-bucket \ --endpoint-url http://localhost:4572
S3からローカルにダウンロードして内容を確認します。
$ aws s3 cp s3://aws-glue-local-test-bucket ~/Downloads/aws-glue-local-test-bucket \ --recursive \ --endpoint-url http://localhost:4572
最後に
AWS Glueの開発において、今まで時間がかかっていたデバッグ作業が改善できました。pytestで単体テストを実装することもできるので、AWS環境へデプロイ前に簡単な動作確認ができそうです。Glue Python ETLライブラリは発展途上で、まだ不足している機能がたくさんあります。今後のアップデートに期待しています。
参考
Developing and Testing ETL Scripts Locally Using the AWS Glue ETL Library